/**
 * @(#)SplitFilter.java
 *
 * Copyright: Copyright (c) 2003 Carnegie Mellon University
 *
 * This program is the implementation of the original system in the Assignment 1 of "Architectures
 * of Software Systems" class. For the details of each classes, please refer to the provided javadoc
 * documents. You will also find some useful information such as implementation decisions, coding
 * standards, and naming conventions in the README file.
 *
 * History:
 *
 * Date          Author              Change
 * ----------    ----------------    ---------------------------------------------------------------
 * 07/15/2003    Jung Soo Kim        Initial version.
 */


import java.io.*;


/**
 * A split filter has one input port and two output ports. It reads data from the input port and
 * pass them to one of the output ports according to a certain condition. Here, data are passed to
 * the first output port if a student's program is equal to the given program name.
 *
 * @author Jung Soo Kim
 * @version 1.0
 */
public class SplitFilter extends Filter {

    /**
     * The input port.
     **/
    protected BufferedReader pInput;

    /**
     * The first output port.
     **/
    protected BufferedWriter pOutput1;

    /**
     * The second output port.
     **/
    protected BufferedWriter pOutput2;

    /**
     * A program name for splitting
     **/
    protected String sProgram;

    /**
     * Construct a split filter with the given name. A split filter requires an input port and
     * two output ports. Ports are expected to be wrapped into a buffered character stream. This
     * approach enables using various different kinds of I/O mechanisms as well as pipes.
     * For example, a file can be directly plugged into a filter.
     *
     * @param sName    the string representing this filter's name
     * @param pInput   the input port of this filter
     * @param pOutput1 the first (accepted) output port of this filter
     * @param pOutput2 the second (rejected) output port of this filter
     * @param iCourse  the program name for splitting
     */
    public SplitFilter(String sName, BufferedReader pInput, 
                       BufferedWriter pOutput1, BufferedWriter pOutput2, String sProgram) {
        // Execute parent's constructor first.
        super(sName);

        // Initialize input/output ports.
        this.pInput   = pInput;
        this.pOutput1 = pOutput1;
        this.pOutput2 = pOutput2;

        // Set the program name for splitting.
        this.sProgram = sProgram;
    }

    /**
     * Tells if data are available on the input port.
     *
     * @return <code>true</code> if and only if this filter can read data from the input port.
     * @throws IOException
     */
    protected boolean ready() throws IOException {
        return this.pInput.ready();
    }

    /**
     * Read available data from the input port and write them to one of the output pipes. If the
     * student represented by the read data (a student record) is in the given program name passed
     * when creating this split filter, the read data are written onto the first (accepted) output
     * port. If not, the read data are written onto the second (rejected) output port.
     *
     * @throws IOException
     */
    protected void work() throws IOException {
        // Read a student record from the input port.
        Student objStudent = new Student(this.pInput.readLine());

        // Select which output port to write.
        BufferedWriter pOutput = objStudent.isAffiliatedWith(this.sProgram) ? this.pOutput1 
                                                                            : this.pOutput2;

        // Write the student record to the selected output port.
        pOutput.write(objStudent.toString());
        pOutput.newLine();
        pOutput.flush();
    }
}
